/*

Gamebots UT Copyright (c) 2002, Andrew N. Marshal, Gal Kaminka
Gamebots UT 2003/2004 port Copyright (c) 2005
       Joe Manojlovich, Tim Garwood, Jessica Bayliss
Gamebots Pogamut derivation Copyright (c) 2007, Michal Bida
	- derived mainly from 2002 Marshal, Kaminka version

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This software must also be in compliance with the Epic Games Inc. license for mods which states the following: "Your mods must be distributed solely for free, period. Neither you, nor any other person or party, may sell them to anyone, commercially exploit them in any way, or charge anyone for receiving or using them without prior written consent of Epic Games Inc. You may exchange them at no charge among other end-users and distribute them to others over the Internet, on magazine cover disks, or otherwise for free." Please see http://www.epicgames.com/ut2k4_eula.html for more information.

*/


// Unreal Script :
// Author:

//We've got this class here to allow specators to go through walls
class GBxPlayer extends xPlayer;

//var NameMarker pickup;
var ScriptedTexture Tex;
var GBhud GBHUD;
var GBHUDInteraction GBHUDInter;

var vector NextStartLocation;
var rotator NextStartRotation;

var Actor FocusActor;

replication
{
    // Functions server can call.
    reliable if( Role==ROLE_Authority )
		Test, DrawLine, DrawTraceLine;
}



/*
simulated event PostBeginPlay()
{
	super.PostBeginPlay();
	BotHUD = spawn(class'BotAPI.GBHud', self);

}
*/


function NotifyTakeHit(pawn InstigatedBy, vector HitLocation, int Damage, class<DamageType> damageType, vector Momentum)
{
	super.NotifyTakeHit(InstigatedBy, HitLocation, Damage, damageType, Momentum);

	if(InstigatedBy != none && InstigatedBy.Controller != none && InstigatedBy.Controller.isA('RemoteBot')) {

	    RemoteBot(InstigatedBy.Controller).RemoteNotifyHit(self, Damage, DamageType);

	}
}

function RespawnPlayer(optional vector startLocation, optional rotator startRotation)
{

	NextStartLocation = startLocation;
	NextStartRotation = startRotation;

	//determine if we are spectator, if yes, we just set position and that's it

	if (PlayerReplicationInfo.bIsSpectator || IsInState('Spectating'))
	{
		//log("We recognized that we are spectationg");
		if (startLocation != vect(0,0,0))
		{
			bBehindView = false;
			bFrozen = false;
			ServerViewSelf();

   			SetLocation(startLocation);
   			ClientSetRotation(startRotation);
			//SetRotation(startRotation);
			//HACK: SetRotation doesnt work.. :-/ did it like this:
			  /*
			if (FocusActor == none)
			{
				FocusActor = Spawn(class'BotAPI.FocusActorClass',self,,startLocation+100*vector(startRotation),);
				FocusActor.bHidden = true;
			}
			else
				FocusActor.setLocation(startLocation+100*vector(startRotation));

			SetViewTarget(FocusActor);*/
		}

		return;

	}

	//if we are not spectator, we will destory pawn set variables and call respawn function

   	if (Pawn != None)
   	{
		Pawn.Destroy();
		Pawn = none;
	}

	BotDeathMatch(Level.Game).RestartPlayer( self );
}

//We override this to disable pausing of the game when pressing ESC key
function ShowMidGameMenu(bool bPause)
{
	// Pause if not already
	//if(Level.Pauser == None)
	//	SetPause(true);

	if ( Level.NetMode != NM_DedicatedServer )
		StopForceFeedback();  // jdf - no way to pause feedback

	// Open menu

	if (bDemoOwner)
		ClientopenMenu(DemoMenuClass);

	else if ( LoginMenuClass != "" )
		ClientOpenMenu(LoginMenuClass);

	else ClientOpenMenu(MidGameMenuClass);
}

function Test()
{
	DrawStayingDebugLine(Pawn.Location,Pawn.Location + 500 * vector(Pawn.Rotation),255,0,0);
	log("In GBxPLayer test() this location: "$Pawn.Location);
}

simulated function DrawTraceLine(vector LineStart,vector LineEnd,bool LineHit)
{
	if (LineHit)
	{
		DrawDebugLine(LineStart,LineEnd,255,0,0);
		log("Draw Line hit");
	}
	else
	{
		DrawDebugLine(LineStart,LineEnd,0,255,0);
		log("Draw Line miss");
	}

}

simulated function DrawLine(vector LineStart,vector LineEnd)
{

	DrawStayingDebugLine(LineStart,LineEnd,255,0,0);
	log("Drawing Line");

}

//We need to change this fc a little bit so our bots can receive msgs from players
function ServerSay( string Msg )
{
	local controller C;

	// center print admin messages which start with #
	if (PlayerReplicationInfo.bAdmin && left(Msg,1) == "#" )
	{
		Msg = right(Msg,len(Msg)-1);
		for( C=Level.ControllerList; C!=None; C=C.nextController )
		{
			if( C.IsA('PlayerController') )
			{
				PlayerController(C).ClearProgressMessages();
				PlayerController(C).SetProgressTime(6);
				PlayerController(C).SetProgressMessage(0, Msg, class'Canvas'.Static.MakeColor(255,255,255));
			}
			if( C.IsA('RemoteBot') )
			{
				RemoteBot(C).RemoteNotifyClientMessage( PlayerReplicationInfo.PlayerName, Msg );
			}

		}
		return;
	}

	for( C=Level.ControllerList; C!=None; C=C.nextController )
	{
		if( C.IsA('RemoteBot') )
		{
			RemoteBot(C).RemoteNotifyClientMessage( PlayerReplicationInfo.PlayerName, Msg );
		}

	}

	Level.Game.Broadcast(self, Msg, 'Say');
}

simulated event Destroyed()
{

	local LinkedReplicationInfo PRI;

    //Destroying all linked replication infos
	for (PRI = PlayerReplicationInfo.CustomReplicationInfo; PRI != none; PRI = PRI.NextReplicationInfo)
	{
		PRI.Destroy();
	}

	Super.Destroyed();

	if (GBHUD != none)
	{
		log("Detroying hud");
		GBHUD.Destroy();
	}

}

function ServerTeamSay( string Msg )
{
	local Controller C;

	LastActiveTime = Level.TimeSeconds;

	if( !GameReplicationInfo.bTeamGame )
	{
		Say( Msg );
		return;
	}

    for( C=Level.ControllerList; C!=None; C=C.nextController )
	{
		if( C.IsA('RemoteBot') && (C.PlayerReplicationInfo.Team.TeamIndex == PlayerReplicationInfo.Team.TeamIndex) )
		{
			RemoteBot(C).RemoteNotifyTeamMessage( PlayerReplicationInfo.PlayerName, Msg );
		}

	}

    Level.Game.BroadcastTeam( self, Level.Game.ParseMessageString( Level.Game.BaseMutator , self, Msg ) , 'TeamSay');
}

state Spectating
{
    ignores SwitchWeapon, RestartLevel, ClientRestart, Suicide,
     ThrowWeapon, NotifyPhysicsVolumeChange, NotifyHeadVolumeChange;

    exec function Fire( optional float F )
    {
    	if ( bFrozen )
	{
		if ( (TimerRate <= 0.0) || (TimerRate > 1.0) )
			bFrozen = false;
		return;
	}

        ServerViewNextPlayer();
    }

    // Return to spectator's own camera.
    exec function AltFire( optional float F )
    {
        bBehindView = false;
        ServerViewSelf();
    }

    function Timer()
    {
    	bFrozen = false;
    }

    function BeginState()
    {
        if ( Pawn != None )
        {
            SetLocation(Pawn.Location);
            UnPossess();
        }
		//log("We are in spect. state, setting collisions off");
        bCollideWorld = false;

	CameraDist = Default.CameraDist;
    }

    function EndState()
    {
        PlayerReplicationInfo.bIsSpectator = false;
        bCollideWorld = false;
    }
}

auto state PlayerWaiting
{
ignores SeePlayer, HearNoise, NotifyBump, TakeDamage, PhysicsVolumeChange, NextWeapon, PrevWeapon, SwitchToBestWeapon;

    exec function Jump( optional float F )
    {
    }

    exec function Suicide()
    {
    }

    function ServerRestartPlayer()
    {
        if ( Level.TimeSeconds < WaitDelay )
            return;
        if ( Level.NetMode == NM_Client )
            return;
        if ( Level.Game.bWaitingToStartMatch )
            PlayerReplicationInfo.bReadyToPlay = true;
        else
            Level.Game.RestartPlayer(self);
        }

    exec function Fire(optional float F)
    {
        LoadPlayers();
        if ( !bForcePrecache && (Level.TimeSeconds > 0.2) )
			ServerReStartPlayer();
    }

    exec function AltFire(optional float F)
    {
        Fire(F);
    }

    function EndState()
    {
        if ( Pawn != None )
            Pawn.SetMesh();
        if ( PlayerReplicationInfo != None )
			PlayerReplicationInfo.SetWaitingPlayer(false);
        bCollideWorld = false;
    }

    function BeginState()
    {
		CameraDist = Default.CameraDist;
        if ( PlayerReplicationInfo != None )
            PlayerReplicationInfo.SetWaitingPlayer(true);
		//log("We are in playerwaiting, setting collisions off");
        bCollideWorld = false;


    }
}

defaultproperties
{
	PawnClass=BotAPI.GBxPawn
}
